var folderplus = {

	/**
	 * Go to folder of current message Always use the first tab of type "Folder"
	 * Don't use a tab as gloda search Change folder even if message already
	 * visible in a virtual folder.
	 */
	goToFolder : function() {
		var aMsgHdr = gFolderDisplay.selectedMessage;
		var folder = gFolderTreeView.getFolderForMsgHdr(aMsgHdr);
		this._GoToFolder(folder, aMsgHdr);
	},

	/**
	 * Same as goToFolder. Maybe it will be changed in future :-/
	 */
	goToThread : function() {
		folderplus.log("folderDisplay.goToThread");
		var aMsgHdr = gFolderDisplay.selectedMessage;
		function callback(aFolderURI){
			folderplus.log("goToThread.callback" + aFolderURI);
			var folder = GetMsgFolderFromUri(aFolderURI);
			folderplus._GoToFolder(folder, aMsgHdr);
		};
		folderplus._getFolder(aMsgHdr, callback);
	},
	
	goToLastMoved : function () {
		folderplus.log("folderDisplay.goToLastMoved");
		var folderId = pref.getCharPref("mail.last_msg_movecopy_target_uri");
		var folder = GetMsgFolderFromUri(folderId, false)
		this._GoToFolder(folder, null);
	},

	goToInbox : function () {
		folderplus.log("folderDisplay.goToInbox");
		var defaultAccountRootFolder = GetDefaultAccountRootFolder();

		// if no default account, get msg isn't going do anything anyways
		// so bail out
		if (!defaultAccountRootFolder)
			return;
		
		var inboxFolder = defaultAccountRootFolder.getFolderWithFlags(Components.interfaces.nsMsgFolderFlags.Inbox);
		
		if (!inboxFolder)
			return;
		
		this._GoToFolder(inboxFolder, null);
	},

	/**
	 * Go to folder of current message Always use the first tab of type "Folder"
	 * Don't use a tab as gloda search Change folder even if message already
	 * visible in a virtual folder.
	 */
	_GoToFolder : function(folder, aMessage) {
		folderplus.log("folderDisplay._GoToFolder");
		folderplus.log("folder = " + folder);
		// inspired from MsgDisplayMessageInFolderTab
		// but force using first tab to manage virdual folder.
		var tabmail = document.getElementById("tabmail");
		var folderTabs = tabmail.tabModes["folder"];
		var folderTab = folderTabs.tabs[0];
		var folderDisplay = folderTab.folderDisplay;
		folderDisplay.selectMessageComingUp();
		tabmail.switchToTab(folderTab);
		if (folderDisplay.displayedFolder != folder
				|| folderDisplay.view.isVirtual) {
			// Force select the folder
			folderDisplay.show(folder);
			gFolderTreeView.selectFolder(folder, true);
		}
		// Force select the message
		if (aMessage) {
			folderplus.log("call folderDisplay.selectMessage" + aMessage.messageId);
			var folderDB = GetMsgFolderFromUri(folder.URI, false); 
			var message = folderDB.msgDatabase.getMsgHdrForMessageID(aMessage.messageId);
			folderDisplay.selectMessage(message);	
		}
	},

	/**
	 * 
	 */
	moveToThreadFolder : function() {
		var aMsgHdr = gFolderDisplay.selectedMessage;
		folderplus.log("moveToThreadFolder" + aMsgHdr.messageKey);
		function callback(aFolderURI){
			/* Comme l'exec du callback est asynchrone (du lancement de la commande)
			 * si utilisation du bouton droit, le message qui a reçu le bouton droit
			 * peut être different du message courant quand le callback est executé.
			 */
			var aMsgHdr = gFolderDisplay.selectedMessage;
			folderplus.log("moveToThreadFolder.callback" + aFolderURI + "," + aMsgHdr.messageKey);
			var folder = GetMsgFolderFromUri(aFolderURI);
			// use MsgMoveMessage to set "move again"
			MsgMoveMessage(folder);
		};
		folderplus._getFolder(aMsgHdr, callback);
	},
	
	/**
  	 * 
	 */
	moveAndGoToThreadFolder : function() {
		/** Bug : le message n'est pas sélectionné après le déplacement. Peut-être car l'appel
		 * selectMessage est fait trop tôt.
		 */
		folderplus.log("folderDisplay.moveAndGoToThreadFolder");
		var aMsgHdr = gFolderDisplay.selectedMessage;
		folderplus.log("message=" + aMsgHdr.messageId);
		function callback(aFolderURI){
			folderplus.log("moveToThreadFolder.callback" + aFolderURI);
			var folder = GetMsgFolderFromUri(aFolderURI);
			// use MsgMoveMessage to set "move again"
			MsgMoveMessage(folder);
			folderplus._GoToFolder(folder, aMsgHdr);
		};
		folderplus._getFolder(aMsgHdr, callback);
	},
	
	/**
	 * set move to conversation and go to folder menu in mailContext menu
	 * and go menu.
	 * Async method :-/ First call a globa search to get a gloda message from 
	 * aMsgHdr then call a second gloda search to find all messages from the 
	 * conversation.
	 */
	fillMailContextMenu : function(event) {
		var aMsgHdr = gFolderDisplay.selectedMessage;
		if (aMsgHdr == null) {
			return;
		}
		folderplus.log(aMsgHdr.messageKey);
		// Update lables menus which talk about Folder (and not conversation)
		var folderName = aMsgHdr.folder.prettyName;
		folderplus._updateAllFolderMenus(folderName);

		function callback(aFolderURI){
			folderplus.log("fillMailContextMenu.callback");
			var label = "";
			if (aFolderURI == "error") {
				folderplus.log("fillMailContextMenu.callback:string");
				label = "?";
			} else {
				folderplus.log("fillMailContextMenu.callback:!string");
				// get the msg folder we're moving messages into
				var destMsgFolder = GetMsgFolderFromUri(aFolderURI);
				var folderName = destMsgFolder.prettyName;
				label = folderName;
			}
			folderplus._updateAllCoversationMenus(label);
		};
		this._getFolder(aMsgHdr, callback);
	},
	
	onMessageSelect : function () {
		folderplus.log("onMessageSelect");
		folderplus._updateStatusBar();
	},
	
	/**
	 * set move to conversation and go to folder menu in mailContext menu
	 * and go menu.
	 * Async method :-/ First call a globa search to get a gloda message from 
	 * aMsgHdr then call a second gloda search to find all messages from the 
	 * conversation.
	 * @return nothing, use the callback.
	 */
	_getFolder : function(aMsgHdr, callback) {
		// cf msgHdrViewOverlay.js/ConversationOpener
		/* Second, look for a conversation from gloda message. */
		var aConvListener = {
			onItemsAdded : function myListener_onItemsAdded(aItems, aCollection) {},
			onItemsModified : function myListener_onItemsModified(aItems,aCollection) {},
			onItemsRemoved : function myListener_onItemsRemoved(aItems,aCollection) {},
			onQueryCompleted : function myListener_onQueryCompleted(aCollection) {
				try {
					if (!aCollection.items.length) {
						throw "Couldn't find conversation message for msg: " + aMsgHdr.messageId;
					} else {
						var folderURI = folderplus._findConversationFolder(aCollection.items);
						callback(folderURI);
					}
				} catch (e) {
					Components.utils.reportError(e);
					callback("error");
				}
			}
		};
		/* First, look for a gloda message from messege header. */
		var aListener = {
			onItemsAdded : function myListener_onItemsAdded(aItems, aCollection) {},
			onItemsModified : function myListener_onItemsModified(aItems,aCollection) {},
			onItemsRemoved : function myListener_onItemsRemoved(aItems,aCollection) {},
			onQueryCompleted : function myListener_onQueryCompleted(aCollection) {
				try {
					if (!aCollection.items.length) {
						throw "Couldn't find a glodaMessage for msg: " + aMsgHdr.messageId;
					} else {
						var aGlodaMessage = aCollection.items[0];
						var aConvCollection = aGlodaMessage.conversation
								.getMessagesCollection(aConvListener);
					}
				} catch (e) {
					Components.utils.reportError(e);
					callback("error");
				}
			}
		};
		if (aMsgHdr == null) {
			callback("error");
		} else {
			var aCollection = Gloda.getMessageCollectionForHeader(aMsgHdr, aListener);
		}
	},
	
	/**
	 * The function which decide which Folder use as the conversation folder.
	 * Currenlty, use the folder of the first message of the conversation.
	 * @params message collection
	 * @return folderURI
	 */
	_findConversationFolder : function (items) {
		var firstDate = null;
		var firstMessage = null;
		for ( var i = 0; i < items.length; i++) {
			var aItem = items[i];
			var aDate = aItem.folderMessage.date;
			var aFolder = aItem.folderMessage.folder.URI;
			if (firstDate == null || (aDate < firstDate)) {
				firstDate    = aItem.folderMessage.date;
				firstMessage = aItem; 
			}
		}
		return firstMessage.folderURI;
	},
	
	/**
	 * Update all Folder menu labels.
	 */
	_updateAllFolderMenus : function (folderName) {
		var bundle = document.getElementById("folderplus-strings");
		var aLabel = bundle.getFormattedString("folderplus.GoToFolder",[ folderName ], 1);
		var aMenuItem = document.getElementById("folderplus.GoToFolder.mailContext");
		aMenuItem.label = aLabel;
		aMenuItem = document.getElementById("folderplus.GoToFolder.goMenu");
		aMenuItem.label = aLabel;
		document.getElementById("folderplus_appmenu_GoToFolder").label = aLabel;
	},
	
	/**
	 * Update all conversation menu labels with folder name.
	 */
	_updateAllCoversationMenus : function (folderName) {
		var bundle = document.getElementById("folderplus-strings");
		var aLabel     = bundle.getFormattedString("folderplusMoveToConversation", [ folderName ], 1);
		var aLabelMenu = bundle.getFormattedString("folderplusMoveToConversationMenu", [ folderName ], 1);
		
		var aMenuItem = document.getElementById("folderplus.moveToConversationFolder");
		aMenuItem.label = aLabel;
		aMenuItem = document.getElementById("folderplus.GoToConversation");
		aMenuItem.label = aLabel;
		aMenuItem = document.getElementById("folderplus.GoToConversation.goMenu");
		aMenuItem.label = aLabel;
		document.getElementById("folderplus_appmenu_goToConversation").label = aLabel;
		aMenuItem = document.getElementById("folderplus.moveToConversationFolder.messageMenu");
		aMenuItem.label = aLabelMenu;
		document.getElementById("folderplus_appmenu_moveToConversationFolder").label = aLabelMenu;
	},
	
	_updateStatusBar : function () {
 		folderplus.log("_updateStatusBar");
		var aMsgHdr = gFolderDisplay.selectedMessage;
		function callback(aFolderURI){
			folderplus.log("onMessageSelect.callback" + aFolderURI);
			if (aFolderURI == "error") {
				label = "?";
			} else {
				// get the msg folder we're moving messages into
				var destMsgFolder = GetMsgFolderFromUri(aFolderURI);
				var folderName = destMsgFolder.prettyName;
				label = folderName;
			}
			document.getElementById('folderplus.statusbar').setAttribute("label", "conv. : " + label);
		};
		folderplus._getFolder(aMsgHdr, callback);
	},
	
	_updateMessageHeader : function () {
		folderplus.log("_updateMessageHeader");
		var aMsgHdr = gFolderDisplay.selectedMessage;
		function callback(aFolderURI){
			folderplus.log("_updateMessageHeader.callback" + aFolderURI);
			if (aFolderURI == "error") {
				label = "?";
			} else {
				// get the msg folder we're moving messages into
				var destMsgFolder = GetMsgFolderFromUri(aFolderURI);
				var folderName = destMsgFolder.prettyName;
				label = folderName;
			}
			document.getElementById("expandedconvestionBox").headerValue=label;	
		};
		folderplus._getFolder(aMsgHdr, callback);
	},

	init : function() {
		folderplus._console = Components.classes["@mozilla.org/consoleservice;1"].
			getService(Components.interfaces.nsIConsoleService);
		var prefs = Components.classes["@mozilla.org/preferences-service;1"]
                    .getService(Components.interfaces.nsIPrefService);
		this._prefs = prefs.getBranch("extensions.folderplus.");
		
		folderplus.log("init");
		
		if (!this._prefs.getBoolPref("firstRunDone")) {
			this._prefs.setBoolPref("firstRunDone", true);
			this._installButton("header-view-toolbar", "folderplusHdrConversationButton");
		}

		//document.getElementById("threadTree").addEventListener("select",
		//		folderplus.onMessageSelect, false);
		//document.getElementById('tabmail').registerTabMonitor(this._folderplusTabMonitor);
		
		gMessageListeners.push({
			onStartHeaders: function () {},
			onEndHeaders: function() {
				folderplus._updateMessageHeader();  
			},
			onEndAttachments: function () {},
		});
	},
	
	
	log : function (aMessage) {
		var logLevel = this._prefs.getCharPref("logLevel");
		if (logLevel == "debug") {
			this._console.logStringMessage(aMessage);
		}
	},
	
	_prefs : null,
	_console : null,	
	
	_folderplusTabMonitor : {
		monitorName: "folderplus",
		
		// Unused, but needed functions
		onTabTitleChanged: function() {},
		onTabOpened: function() {},
		onTabClosing: function() {},
		onTabPersist: function() {},
		onTabRestored: function() {},
		
		onTabSwitched: function onTabSwitched(aNewTab, aOldTab) {
		// Unfortunately, tabmail doesn't provide a hideTab function on the tab
		// type definitions. To make sure the commands are correctly disabled,
		// we want to update calendar/task commands when switching away from
		// those tabs.
		folderplus.log("onTabSwitched");
		folderplus._updateStatusBar();
		}
	},

	/**
	 * Installs the toolbar button with the given ID into the given
	 * toolbar, if it is not already present in the document.
	 *
	 * @param {string} toolbarId The ID of the toolbar to install to.
	 * @param {string} id The ID of the button to install.
	 * @param {string} afterId The ID of the element to insert after. @optional
	 */
	_installButton : function (toolbarId, id, afterId) {
	    if (!document.getElementById(id)) {
		var toolbar = document.getElementById(toolbarId);
	 
		// If no afterId is given, then append the item to the toolbar
		var before = null;
		if (afterId) {
		    let elem = document.getElementById(afterId);
		    if (elem && elem.parentNode == toolbar)
			before = elem.nextElementSibling;
		}
	 
		toolbar.insertItem(id, before);
		toolbar.setAttribute("currentset", toolbar.currentSet);
		document.persist(toolbar.id, "currentset");
	 
		if (toolbarId == "addon-bar")
		    toolbar.collapsed = false;
	    }
	}
};

window.addEventListener("load", function load(event){
    window.removeEventListener("load", load, false); //remove listener, no longer needed
    folderplus.init();
}, false);
